package com.allen.study.test_common.base;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.util.MapUtils;
import org.apache.commons.lang3.ObjectUtils;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: TreeNode
 * @Author: AllenSun
 * @Date: 2025/3/11 22:58
 */
public class TreeNode<T extends TreeNode> {

    public static final String DEFAULT_ROOT_ID = "0";
    public static final String ROOT_NODE_NOT_EXISTS = "根节点不存在";
    private String id;
    private String name;
    private String parentId;
    private boolean disabled = false;
    private int level;
    private List<T> children;

    private int value;

    private int valueSumChild;


    public void setId(String id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setParentId(String parentId) {
        this.parentId = parentId;
    }

    public void setDisabled(boolean disabled) {
        this.disabled = disabled;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public int getValueSumChild() {
        return valueSumChild;
    }

    public void setValueSumChild(int valueSumChild) {
        this.valueSumChild = valueSumChild;
    }

    public void setChildren(List<T> children) {
        this.children = children;
    }

    public String getId() {
        return this.id;
    }

    public String getName() {
        return this.name;
    }

    public String getParentId() {
        return this.parentId;
    }

    public boolean isDisabled() {
        return this.disabled;
    }

    public int getLevel() {
        return this.level;
    }

    public List<T> getChildren() {
        return this.children;
    }

    public int calculateSum() {
        int sum = value;
        if (ObjectUtil.isNotNull(children)) {
            for (TreeNode child : children) {
                sum += child.calculateSum();
            }
        }
        return sum;
    }

    public static <T extends TreeNode<T>> T toTree(@NotNull List<T> list, @NotNull boolean computeChildIndSum,@NotNull String rootId) {
        return toTree(list, rootId,computeChildIndSum);
    }

    public static <T extends TreeNode<T>> T toTree(@NotNull List<T> nodes, @NotNull String rootId, @NotNull boolean computeChildIndSum) {
        TreeNode treeNode=null;
        Map<String, T> map = MapUtils.newHashMap();
        T rootNode = null;
        for (TreeNode treeNode1 : nodes) {
            if(ObjectUtils.equals(rootId, treeNode1.getId())) {
                treeNode = treeNode1;
            }
            map.put(treeNode1.getId(), (T)treeNode1);
        }
        if (treeNode==null) {
            return null;
        }
        treeNode.setLevel(0);
        for (TreeNode treeNode2 : nodes) {
            String parentId = treeNode2.getParentId();
            TreeNode treeNode1 = (TreeNode)map.get(parentId);
            if (treeNode1== null) {
                continue;
            }
            List<T> children = treeNode1.getChildren();
            if (children == null) {
                children = new ArrayList<>();
                treeNode1.setChildren(children);
            }
            children.add((T)treeNode2);
        }
        if (computeChildIndSum) {
            computeChildIndSum(nodes);
        }
        computeLevel(treeNode.getChildren(), 1);
        return (T)treeNode;
    }

    public static <T extends TreeNode<T>> List<T> toTreeList(@NotNull List<T> nodes, @NotNull String rootId) {
        List<TreeNode> treeNodes = new ArrayList<>();
        Map<String, T> map = MapUtils.newHashMap();
        T rootNode = null;
        for (TreeNode treeNode1 : nodes) {
            if(ObjectUtils.equals(rootId, treeNode1.getParentId())) {
                treeNode1.setLevel(1);
                treeNodes.add(treeNode1);
            }
            map.put(treeNode1.getId(), (T)treeNode1);
        }

        if(treeNodes.size() ==0){
            return Collections.EMPTY_LIST;
        }


        for (TreeNode treeNode2 : nodes) {
            String parentId = treeNode2.getParentId();
            TreeNode treeNode1 = (TreeNode)map.get(parentId);
            if (treeNode1== null) {
                continue;
            }
            List<T> children = treeNode1.getChildren();
            if (children == null) {
                children = new ArrayList<>();
                treeNode1.setChildren(children);
            }
            children.add((T)treeNode2);
        }

        treeNodes.forEach(treeNode -> {
            computeLevel(treeNode.getChildren(), 2);
        });
        return (List) treeNodes;
    }

    private static <T extends TreeNode<T>> void computeLevel(List<T> nodes, int level) {
        if (nodes == null) {
            return;
        }
        for (TreeNode<T> treeNode : nodes) {
            treeNode.setLevel(level);
            computeLevel(treeNode.getChildren(), level + 1);
        }
    }

    private static <T extends TreeNode<T>> void computeChildIndSum(List<T> nodes) {
        if (nodes == null) {
            return;
        }
        for (TreeNode treeNode3 : nodes) {
            int sum = treeNode3.calculateSum();
            treeNode3.setValueSumChild(sum);
            treeNode3.setName(treeNode3.getName()+"("+sum+")");
        }
    }
}

